package com.bruce.rpc.registry;

import com.bruce.rpc.connection.ZkConnection;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.util.List;

/**
 * @author Bruce
 */
public class RpcRegistry {
    private ZkConnection connection;
    private String ip;
    private int port;

    /**
     * 注册服务
     * @param serviceInterface 服务接口类对象
     * @param serviceObject 服务实现类对象
     */
    public void registerService(Class<? extends Remote> serviceInterface, Remote serviceObject) throws IOException, InterruptedException, KeeperException {
        String rmi = "rmi://" + ip + ":" + port + "/" + serviceInterface.getName();
        String path = "/bruce/rpc/" + serviceInterface.getName();
        List<String> children = connection.getConnection().getChildren("/bruce/rpc", false);
        if (children.contains(serviceInterface.getName())){
            //节点存在，需要删除
            Stat stat = new Stat();
            connection.getConnection().getData(path, false, stat);
            connection.getConnection().delete(path, stat.getCversion());
        }
        connection.getConnection().create(path, rmi.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        Naming.rebind(rmi, serviceObject);

    }

    public <T extends Remote> T getServiceProxy(Class<T> serviceInterface) throws IOException, InterruptedException, KeeperException, NotBoundException {
        String path = "/bruce/rpc/" + serviceInterface.getName();

        byte[] datas = connection.getConnection().getData(path, false, null);

        String rmi = new String(datas);

        Object obj = Naming.lookup(rmi);

        return (T) obj;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public ZkConnection getConnection() {
        return connection;
    }

    public void setConnection(ZkConnection connection) {
        this.connection = connection;
    }
}
